///
/// ArmyBodger 3
/// (c)2010 richyp
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using ArmyBodger.Core;

namespace ArmyBodger.UI {
    /// <summary>
    /// The EntryItem is a visual wrapper around an Entry, or Category and is used
    /// directly by the EntryListControl class
    /// </summary>
    public class EntryItem : Panel {
        #region Properties and Variables
        /// <summary>
        /// Is this EntryItem Selected
        /// </summary>
        private bool selected = false;
        /// <summary>
        /// Button to add a PrimaryUnit to the Entry
        /// </summary>
        protected Button incrementButton = new Button();
        /// <summary>
        /// Button to remove a PrimaryUnit from the Entry
        /// </summary>
        protected Button decrementButton = new Button();
        /// <summary>
        /// Collapse/Expand entry button
        /// </summary>
        protected Button collapseButton = new Button();
        /// <summary>
        /// Remove this entry
        /// </summary>
        protected Button removeEntry = new Button();
        /// <summary>
        /// Inline drop down to add/remove units to this entry
        /// </summary>
        protected ComboBox addUnitComboBox = new ComboBox();
        /// <summary>
        /// Inline drop down to add/remove upgrades to this entry
        /// </summary>
        protected ComboBox upgradesComboBox = new ComboBox();
        /// <summary>
        /// Add the chosen unit from the units drop down
        /// </summary>
        protected Button addUnitButton = new Button();
        /// <summary>
        /// Remove the chosen unit from the units drop down
        /// </summary>
        protected Button removeUnitButton = new Button();
        /// <summary>
        /// Add the chosen upgrade from the upgrades drop down
        /// </summary>
        protected Button addUpgradeButton = new Button();
        /// <summary>
        /// Remove the chose upgrade from the upgrades drop down
        /// </summary>
        protected Button removeUpgradeButton = new Button();
        /// <summary>
        /// Is this Entry Collapsed?
        /// </summary>
        public bool Collapsed { get; set; }
        /// <summary>
        /// The From colour used by the gradient paint
        /// </summary>
        public Color fromColor = Color.FromArgb(240, 240, 240);
        /// <summary>
        /// The To colour used by the gradient paint
        /// </summary>
        protected Color toColor = Color.White;
        /// <summary>
        /// Get/Set the Entry referred to in this EntryItem
        /// </summary>
        public Entry Entry { get; set; }
        /// <summary>
        /// Get/Set the category name if this is a category item
        /// </summary>
        public string Category { get; set; }
        /// <summary>
        /// The font used in the title line
        /// </summary>
        protected Font titleFont = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Bold);
        /// <summary>
        /// The font used in the entry description line
        /// </summary>
        protected Font subTitleFont = new Font(FontFamily.GenericSansSerif, 7);
        /// <summary>
        /// The colour of the titles
        /// </summary>
        protected Brush titleBrush = new SolidBrush(Color.Black);
        #endregion
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="entry">The Entry object to wrap</param>
        public EntryItem(Entry entry) {
            this.Selected = false;
            this.Entry = entry;
            this.TotalItem = false;
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.Height = 40;
            this.titleFont = new Font(this.Font, FontStyle.Bold);
            this.Click += new EventHandler(entryItem_Click);
            if (entry != null) { // This is an actual Entry object not a category or total
                this.incrementButton.Text = "+";
                this.decrementButton.Text = "-";
                this.incrementButton.Width = this.decrementButton.Width = 16;
                this.incrementButton.Height = this.decrementButton.Height = 16;
                this.incrementButton.Left = this.Width - 234;
                this.incrementButton.Top = 2;
                this.incrementButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                this.decrementButton.Left = this.incrementButton.Left + this.incrementButton.Width;
                this.decrementButton.Top = 2;
                this.decrementButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                this.incrementButton.Click += new EventHandler(incrementButton_Click);
                this.decrementButton.Click += new EventHandler(decrementButton_Click);

                this.addUnitButton.Font =
                    this.removeEntry.Font =
                    this.removeUnitButton.Font =
                    this.incrementButton.Font =
                    this.decrementButton.Font =
                    this.addUnitComboBox.Font =
                    this.upgradesComboBox.Font =
                    this.addUpgradeButton.Font =
                    this.removeUpgradeButton.Font =
                    this.collapseButton.Font = new Font(FontFamily.GenericSansSerif, 5.5f);
                this.addUnitButton.Text = "Add";
                this.addUnitButton.Width = 28;
                this.addUnitButton.Height = 16;
                this.addUnitButton.Top = 2;
                this.addUnitButton.Left = this.Width - 128;
                this.addUnitButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                this.removeUnitButton.Text = "Del";
                this.removeUnitButton.Width = 28;
                this.removeUnitButton.Height = 16;
                this.removeUnitButton.Top = 2;
                this.removeUnitButton.Left = this.addUnitButton.Left + 28;
                this.removeUnitButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                this.removeUnitButton.Click += new EventHandler(removeUnitButton_Click);
                this.addUnitComboBox.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                this.addUnitComboBox.Left = this.addUnitButton.Left - 72;
                this.addUnitComboBox.Top = 2;
                this.addUnitComboBox.Height = 16;
                this.addUnitComboBox.Width = 72;
                this.addUnitComboBox.SelectedIndexChanged += new EventHandler(addUnitComboBox_SelectedIndexChanged);
                this.addUnitComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
                this.addUnitButton.Click += new EventHandler(addUnitButton_Click);
                this.upgradesComboBox.Anchor = AnchorStyles.Right | AnchorStyles.Top;
                this.upgradesComboBox.Left = this.incrementButton.Left;
                this.upgradesComboBox.Top = 20;
                this.upgradesComboBox.Width = 104;
                this.addUpgradeButton.Text = "Add";
                this.addUpgradeButton.Left = this.addUnitButton.Left;
                this.addUpgradeButton.Width = 28;
                this.addUpgradeButton.Height = 16;
                this.addUpgradeButton.Top = this.upgradesComboBox.Top;
                this.addUpgradeButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                this.addUpgradeButton.Click += new EventHandler(addUpgradeButton_Click);
                this.removeUpgradeButton.Click += new EventHandler(removeUpgradeButton_Click);
                this.removeUpgradeButton.Text = "Del";
                this.removeUpgradeButton.Left = this.removeUnitButton.Left;
                this.removeUpgradeButton.Width = 28;
                this.removeUpgradeButton.Height = 16;
                this.removeUpgradeButton.Top = this.upgradesComboBox.Top;
                this.removeUpgradeButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;

                this.upgradesComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
                this.upgradesComboBox.SelectedIndexChanged += new EventHandler(upgradesComboBox_SelectedIndexChanged);
                this.Controls.Add(this.incrementButton);
                this.Controls.Add(this.decrementButton);
                this.Controls.Add(this.addUnitComboBox);
                this.Controls.Add(this.addUnitButton);
                this.Controls.Add(this.removeUnitButton);
                this.Controls.Add(this.addUpgradeButton);
                this.Controls.Add(this.removeUpgradeButton);
                this.Controls.Add(this.upgradesComboBox);


                this.collapseButton.Width = 16;
                this.collapseButton.Height = 16;
                this.collapseButton.Top = 2;
                this.collapseButton.Left = 2;
                this.collapseButton.Text = "v";
                this.collapseButton.Click += new EventHandler(collapseButton_Click);
                this.Controls.Add(this.collapseButton);
                this.removeEntry.Width = 16;
                this.removeEntry.Height = 16;
                this.removeEntry.Top = 2;
                this.removeEntry.Left = 18;
                this.removeEntry.Text = "x";
                this.removeEntry.BackColor = Color.FromArgb(250, 200, 200);
                this.removeEntry.Click += new EventHandler(removeEntry_Click);
                this.Controls.Add(this.removeEntry);
                this.SetButtonStates();
            }
        }
        /// <summary>
        /// Any additional error message to display in red
        /// </summary>
        public string ErrorMessage { get; set; }
        /// <summary>
        /// Is this EntryItem Selected
        /// </summary>
        public bool Selected {
            get {
                return this.selected;
            }
            set {
                this.selected = value;
                if (this.Parent != null && value) {
                    EntryListControl parent = (EntryListControl)this.Parent;
                    foreach (EntryItem other in parent.Items) {
                        if (other != this) {
                            other.selected = false;
                            other.SetButtonStates();
                        }
                    }
                    parent.OnSelectionChange(this);
                }
                this.SetButtonStates();
            }
        }
        /// <summary>
        /// Is this EntryItem used to display the total list value instead of an Entry?
        /// </summary>
        public bool TotalItem { get; set; }
        /// <summary>
        /// Update the enabled/disabled/visable status of the inline controls
        /// based on the current Entry
        /// </summary>
        public void SetButtonStates() {
            if (this.Entry != null) {
                string primary = this.Entry.GetPrimary();
                this.addUnitComboBox.Items.Clear();
                foreach (Unit unit in this.Entry.PossibleUnits) {
                    if (!unit.IsPrimary) {
                        bool exists = false;
                        foreach (Unit existing in this.addUnitComboBox.Items) {
                            if (existing.Name == unit.Name) {
                                exists = true;
                                break;
                            }
                        }
                        if (!exists) {
                            this.addUnitComboBox.Items.Add(unit);
                        }
                    }
                }
                this.upgradesComboBox.Items.Clear();
                foreach (Upgrade upgrade in this.Entry.Upgrades) {
                    this.upgradesComboBox.Items.Add(upgrade);
                }
                this.upgradesComboBox.Enabled = this.upgradesComboBox.Items.Count > 0;
                if (this.upgradesComboBox.Items.Count > 0) {
                    this.upgradesComboBox.SelectedIndex = 0;
                }

                if (this.addUnitComboBox.Items.Count > 0) {
                    this.addUnitComboBox.SelectedIndex = 0;
                    this.addUnitComboBox.Enabled = true;
                } else {
                    this.addUnitComboBox.Enabled = false;
                }
                this.addUnitButton.Enabled = false;
                this.removeUnitButton.Enabled = false;


                if (this.addUnitComboBox.SelectedIndex != -1) {
                    Unit current = (Unit)this.addUnitComboBox.SelectedItem;
                    UnitCollection existing = this.Entry.Units.GetUnitsByName(current.Name);
                    if (existing.Count == 0) {
                        this.addUnitButton.Enabled = true;
                        this.removeUnitButton.Enabled = false;
                    } else {
                        if (existing.Count < current.Maximum) {
                            this.addUnitButton.Enabled = true;
                        }
                        if (existing.Count > current.Minimum) {
                            this.removeUnitButton.Enabled = true;
                        }
                    }
                }
                if (primary == "") {
                    this.decrementButton.Enabled = this.incrementButton.Enabled = false;
                }
                if (primary != "") {
                    UnitCollection primaryUnits = this.Entry.Units.GetUnitsByName(primary);
                    this.incrementButton.Enabled = (primaryUnits.Count < primaryUnits[0].Maximum);
                    this.decrementButton.Enabled = (primaryUnits.Count > primaryUnits[0].Minimum);
                }
                bool showControls = false;
                if (!this.Collapsed && this.Selected) {
                    showControls = true;
                }
                if (!this.Selected) {
                    showControls = false;
                }
                showControls = false;
                this.addUnitButton.Visible =
                    this.decrementButton.Visible =
                    this.incrementButton.Visible =
                    this.removeUnitButton.Visible =
                    this.addUnitButton.Visible =
                    this.addUnitComboBox.Visible =
                    this.upgradesComboBox.Visible =
                    this.addUpgradeButton.Visible =
                    this.removeUpgradeButton.Visible = showControls;
            }
        }
        /// <summary>
        /// Overriden onpaint method to do the legwork
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e) {
            base.OnPaint(e);
            Color color = this.fromColor;
            Color color2 = this.toColor;
            Brush textBrush = this.titleBrush;
            if (this.Selected && this.Entry != null) {
                color = Color.Yellow;
                color2 = Color.Tomato;
                textBrush = textBrush;
            }
            LinearGradientBrush lgb = new LinearGradientBrush(
                this.ClientRectangle,
                color,
                color2,
                90
                );
            Pen border = new Pen(this.fromColor);
            e.Graphics.FillRectangle(lgb, this.ClientRectangle);
            e.Graphics.DrawRectangle(border, new Rectangle(0, 0, this.Width - 1, this.Height - 1));
            if (this.Entry == null && !this.TotalItem) {
                e.Graphics.DrawString(this.Category, this.titleFont, textBrush, 2, 2);
            } else if (this.Entry != null && !this.TotalItem) {
                e.Graphics.DrawString(this.Entry.Name, this.titleFont, textBrush, 36, 2);
                int width = (int)
                    e.Graphics.MeasureString(this.Entry.Cost + " pts", this.titleFont).Width;
                width = this.Width - width;
                e.Graphics.DrawString(
                    this.Entry.Cost + "pts",
                    this.titleFont,
                    textBrush,
                    width - 20,
                    2
                    );
                e.Graphics.DrawString(this.Entry.Description, this.subTitleFont, textBrush, 2, 20);
                e.Graphics.DrawLine(Pens.DarkGray, this.Width - 70, 2, this.Width - 70, this.Height - 2);
                e.Graphics.DrawLine(Pens.White, this.Width - 69, 2, this.Width - 69, this.Height - 2);                
                e.Graphics.DrawLine(Pens.DarkGray, 0, this.Height - 1, this.Width, this.Height - 1);
            } else if (this.Entry == null && this.TotalItem) {
                int width = (int)
                    e.Graphics.MeasureString(this.Category, this.titleFont).Width;
                width = this.Width - width;
                e.Graphics.DrawString(
                    this.Category,
                    this.titleFont,
                    this.titleBrush,
                    width - 20,
                    2);
                if (!String.IsNullOrEmpty(this.ErrorMessage)) {
                    e.Graphics.DrawString(
                        this.ErrorMessage,
                        this.titleFont,
                        Brushes.Red,
                        5,
                        2
                        );
                }
            }
        }
        #region EventHandlers
        /// <summary>
        /// Remove Entry/Delete clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void removeEntry_Click(object sender, EventArgs e) {
            ((EntryListControl)this.Parent).RemoveEntry(this.Entry);
        }
        /// <summary>
        /// Remove upgrade button clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void removeUpgradeButton_Click(object sender, EventArgs e) {
            Upgrade upgrade = (Upgrade)this.upgradesComboBox.SelectedItem;
            if (upgrade.Applied) {
                upgrade.Applied = false;
                this.SetButtonStates();
                ((EntryListControl)this.Parent).Render();
            }
        }
        /// <summary>
        /// Add upgrade button clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void addUpgradeButton_Click(object sender, EventArgs e) {
            Upgrade upgrade = (Upgrade)this.upgradesComboBox.SelectedItem;
            bool result = true;
            if (upgrade.OnUpgradeEvent != null && upgrade.OnUpgradeEvent.Length > 0) {
                ScriptCore.Instance.Execute(upgrade.OnUpgradeEvent);
            }
            if (result) {
                upgrade.Applied = true;
                this.SetButtonStates();
                ((EntryListControl)this.Parent).Render();
            }
        }
        /// <summary>
        /// Upgrade Entry changed in the dropdown
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void upgradesComboBox_SelectedIndexChanged(object sender, EventArgs e) {
            Upgrade upgrade = (Upgrade)this.upgradesComboBox.SelectedItem;
            //if (upgrade.Equipment == null)
            //    return;

            if (!this.Entry.Upgrades[upgrade.Equipment.Name].Applied) {
                this.addUpgradeButton.Enabled = true;
                this.removeUpgradeButton.Enabled = false;
            } else {
                this.addUpgradeButton.Enabled = false;
                this.removeUpgradeButton.Enabled = true;
            }
        }
        /// <summary>
        /// This entry was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void entryItem_Click(object sender, EventArgs e) {
            ((EntryListControl)this.Parent).DeselectAll();
            this.Selected = true;
            this.SetButtonStates();
        }
        /// <summary>
        /// Collapse/Expand button was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void collapseButton_Click(object sender, EventArgs e) {
            if (this.Collapsed) {
                this.Height = 40;
            } else {
                this.Height = 20;
            }
            this.Collapsed = !this.Collapsed;
            if (this.Collapsed) {
                this.collapseButton.Text = "^";
            } else {
                this.collapseButton.Text = "v";
            }

            this.SetButtonStates();
            ((EntryListControl)this.Parent).Render();
        }
        /// <summary>
        /// Remove unit button was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void removeUnitButton_Click(object sender, EventArgs e) {
            Unit unit = (Unit)this.addUnitComboBox.SelectedItem;
            Unit removeMe = null;
            foreach (Unit existing in this.Entry.Units) {
                if (existing.Name == unit.Name) {
                    removeMe = existing;
                    break;
                }
            }
            if (removeMe != null) {
                if (unit.Replaces != null && unit.Replaces.Length > 0) {
                    this.Entry.AddUnit(unit.Replaces);
                }
                this.Entry.Units.Remove(removeMe);
            }
            this.SetButtonStates();
            ((EntryListControl)this.Parent).Render();
        }
        /// <summary>
        /// Selected Unit was changed in the dropdown box
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void addUnitComboBox_SelectedIndexChanged(object sender, EventArgs e) {
            Unit selected = (Unit)this.addUnitComboBox.SelectedItem;
            this.addUnitButton.Enabled = false;
            this.removeUnitButton.Enabled = true;
            UnitCollection existing = this.Entry.Units.GetUnitsByName(selected.Name);
            if (existing.Count == 0) {
                this.addUnitButton.Enabled = true;
            } else {
                if (existing.Count < selected.Maximum) {
                    this.addUnitButton.Enabled = true;
                }
            }
            if (existing.Count == 0 || existing.Count == selected.Minimum) {
                this.removeUnitButton.Enabled = false;
            }
        }
        /// <summary>
        /// Add unit button was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void addUnitButton_Click(object sender, EventArgs e) {
            this.Entry.AddUnit(((Unit)this.addUnitComboBox.SelectedItem).Name);
            ((EntryListControl)this.Parent).Render();
            this.SetButtonStates();
        }
        /// <summary>
        /// Decrement (remove a primary unit) button was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void decrementButton_Click(object sender, EventArgs e) {
            string primary = this.Entry.GetPrimary();
            if (primary != "") {
                Unit removeMe = null;
                foreach (Unit unit in this.Entry.Units) {
                    if (unit.Name == primary) {
                        removeMe = unit;
                        break;
                    }
                }
                this.Entry.Units.Remove(removeMe);
            }
            this.SetButtonStates();

            try {
                ((EntryListControl)this.Parent).Render();
            } catch { }

        }
        /// <summary>
        /// Increment (add a primary unit) button was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void incrementButton_Click(object sender, EventArgs e) {
            string primary = this.Entry.GetPrimary();
            if (primary != "") {
                this.Entry.AddUnit(primary);
            }
            try {
                ((EntryListControl)this.Parent).Render();
            } catch { }
            this.SetButtonStates();
        }
        #endregion
    }
}
